﻿/************************************************************************

   Extended Silverlight Toolkit

   Copyright (C) 2010-2012 Xceed Software Inc.

   This program is provided to you under the terms of the Microsoft Public
   License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license

   Please purchase a commercial version of this toolkit if you are using
   it in a commercial product. The commercial versions support the project,
   and also include more features for each control, priority support,
   source code, updates, removed watermark, and a proprietary license.

   Visit http://xceed.com and follow @datagrid on Twitter.

  **********************************************************************/

using System.Windows.Input;
using System;
using Xceed.Silverlight.Data;
using Xceed.Silverlight.Utils;
using System.Collections.Generic;
using System.Windows;

namespace Xceed.Silverlight.ListBox
{
  public class ListBoxGroupHeader : ListBoxContainer
  {
    #region Constructor
    public ListBoxGroupHeader()
    {
      this.DefaultStyleKey = typeof( ListBoxGroupHeader );
    }
    #endregion

    #region IsSelectable Property
    internal override bool IsSelectable
    {
      get
      {
        return false;
      }
    }
    #endregion

    #region NavigateToNextGroupCommand Read-Only Property

    public ICommand NavigateToNextGroupCommand
    {
      get
      {
        if( m_navigateToNextGroupCommandCache == null )
        {
          m_navigateToNextGroupCommandCache = new Command(
            new Action<object>( this.OnNavigateToNextGroupExecuted ),
            new Func<object, bool>( this.OnNavigateToNextGroupCanExecute ) );
        }

        return m_navigateToNextGroupCommandCache;
      }
    }

    #endregion

    #region NavigateToPreviousGroupCommand Read-Only Property

    public ICommand NavigateToPreviousGroupCommand
    {
      get
      {
        if( m_navigateToPreviousGroupCommandCache == null )
        {
          m_navigateToPreviousGroupCommandCache = new Command(
            new Action<object>( this.OnNavigateToPreviousGroupExecuted ),
            new Func<object, bool>( this.OnNavigateToPreviousGroupCanExecute ) );
        }

        return m_navigateToPreviousGroupCommandCache;
      }
    }

    #endregion

    #region GroupValueDataTemplates Property

    public static readonly DependencyProperty GroupValueDataTemplatesProperty = DependencyProperty.Register(
      "GroupValueDataTemplates",
      typeof( List<GroupValueDataTemplate> ),
      typeof( ListBoxGroupHeader ),
      new PropertyMetadata( ( List<GroupValueDataTemplate> )null ) );

    public List<GroupValueDataTemplate> GroupValueDataTemplates
    {
      get
      {
        return ( List<GroupValueDataTemplate> )this.GetValue( ListBoxGroupHeader.GroupValueDataTemplatesProperty );
      }
      internal set
      {
        this.SetValue( ListBoxGroupHeader.GroupValueDataTemplatesProperty, value );
      }
    }

    #endregion

    #region Recycling

    internal override bool DefaultRecycleEvenIfFocused
    {
      get
      {
        // We always want to recycle a group header if it is not part of
        // the layout even though it has the focus.
        return true;
      }
    }

    #endregion

    #region Internal Methods

    internal override void SetDataContextFromDataPath( DataPath dataPath )
    {
      this.DataContext = new GroupDataContext( dataPath, this.ParentListBox.GroupDescriptions );
      this.Content = this.DataContext;

      // Update the states of navigation commands
      this.RaiseExecuteChangedOnAllNavigationCommand();

      // Update the visual state of the container
      this.ChangeVisualState( true );
    }

    #endregion

    #region Private Memebers

    private bool OnNavigateToPreviousGroupCanExecute( object parameter )
    {
      return this.CanNavigateAcrossGroups();
    }

    private bool OnNavigateToNextGroupCanExecute( object parameter )
    {
      return this.CanNavigateAcrossGroups();
    }

    private void OnNavigateToNextGroupExecuted( object parameter )
    {
      // Make sure the parent ListBox isn't null
      if( this.ParentListBox == null )
        return;

      // Forward the command to the parent ListBox so it can navigate to group
      this.ParentListBox.NavigateToNextGroup( this.DataContext );

      m_navigateToNextGroupCommandCache.RaiseCanExecuteChanged();
    }

    private void OnNavigateToPreviousGroupExecuted( object parameter )
    {
      // Make sure the parent ListBox isn't null
      if( this.ParentListBox == null )
        return;

      // Forward the command to the parent ListBox so it can navigate to group
      this.ParentListBox.NavigateToPreviousGroup( this.DataContext );

      m_navigateToPreviousGroupCommandCache.RaiseCanExecuteChanged();
    }

    private void RaiseExecuteChangedOnAllNavigationCommand()
    {
      if( m_navigateToNextGroupCommandCache != null )
      {
        m_navigateToNextGroupCommandCache.RaiseCanExecuteChanged();
      }

      if( m_navigateToPreviousGroupCommandCache != null )
      {
        m_navigateToPreviousGroupCommandCache.RaiseCanExecuteChanged();
      }
    }

    private bool CanNavigateAcrossGroups()
    {
      // Make sure the parent ListBox isn't null
      if( this.ParentListBox == null )
        return false;

      // Make sure the DataPath isn't null
      if( this.DataPath == null )
        return false;

      // We can navigate to group only if the number of group description of the parent ListBox is
      // greater than 0 and if the LastChild is loaded (not dummy).
      return ( ( this.ParentListBox.GroupDescriptions.Count > 0 ) && ( this.DataPath.LastChild.IsLoaded ) );
    }
    #endregion

    #region Private Members

    private Command m_navigateToNextGroupCommandCache;
    private Command m_navigateToPreviousGroupCommandCache;

    #endregion
  }
}
